<?php

namespace addons\thirdwork\library;

use fast\Http;
use think\Cache;
use think\Session;

/**
 * 钉钉
 */
class Dingtalk
{
    const GET_TMP_AUTH_CODE_URL         = 'https://oapi.dingtalk.com/connect/qrconnect';
    const GET_USER_INFO_BYCODE_URL      = 'https://oapi.dingtalk.com/sns/getuserinfo_bycode';
    const GET_USERID_BYUNIONID_URL      = 'https://oapi.dingtalk.com/user/getUseridByUnionid';
    const GET_USER_URL                  = 'https://oapi.dingtalk.com/user/get';

    const GET_ACCESS_TOKEN_URL          = 'https://oapi.dingtalk.com/gettoken';
    const GET_DEPARTMENT_LIST_URL       = 'https://oapi.dingtalk.com/department/list';
    const GET_DEPARTMENT_MEMBER_URL     = 'https://oapi.dingtalk.com/user/getDeptMember';
    const GET_DEPARTMENT_USER_LIST_URL  = 'https://oapi.dingtalk.com/user/listbypage';

    /**
     * 配置信息
     * @var array
     */
    private $config = [];

    public function __construct($options = [])
    {
        if ($config = get_addon_config('thirdwork')['dingtalk']) {
            $this->config = array_merge($this->config, $config);
        }
        $this->config = array_merge($this->config, is_array($options) ? $options : []);
    }

    /**
     * 获取authorize_url
     */
    public function getAuthorizeUrl()
    {
        $state = md5(uniqid(rand(), true));
        Session::set('state', $state);
        $queryarr = array(
            'appid'         => $this->config['appid_qr'],
            'response_type' => 'code',
            'scope'         => 'snsapi_login',
            'redirect_uri'  => $this->config['callback'],
            'state'         => $state,
        );
        request()->isMobile() && $queryarr['display'] = 'mobile';
        $url = self::GET_TMP_AUTH_CODE_URL . '?' . http_build_query($queryarr) . '#dingtalk_redirect';
        return $url;
    }

    /**
     * 获取用户信息
     * @param array $params
     * @return array
     */
    public function getUserInfo($params = [])
    {
        $params = $params ? $params : request()->get();
        if ((isset($params['state']) && $params['state'] == Session::get('state') && isset($params['code']))) {
            //用code换openid和unionid
            $queryarr = [
                'tmp_auth_code' => $params['code'],
            ];
            $timestamp = round(microtime(true) * 1000);
            $url = self::GET_USER_INFO_BYCODE_URL . '?signature=' . $this->getSignature($timestamp) . '&timestamp=' . $timestamp . '&accessKey=' . $this->config['appid_qr'];
            // POST该接口必须为json包体
            $options = array(CURLOPT_HTTPHEADER => ['Content-Type:application/json']);
            $ret = Http::post($url, json_encode($queryarr), $options);
            $ret = (array) json_decode($ret, true);
            if (!isset($ret['user_info']) || $ret['errcode']) {
                return ['errmsg' => '获取个人信息失败'];
            }
            $nick   = $ret['user_info']['nick'];
            $openid = $ret['user_info']['openid'];
            // 用unionid换userid
            $queryarr = [
                'access_token'  => $this->getAccessToken(),
                'unionid'       => $ret['user_info']['unionid']
            ];
            $ret = Http::get(self::GET_USERID_BYUNIONID_URL, $queryarr);
            $ret = (array) json_decode($ret, true);
            if (!isset($ret['userid']) || $ret['errcode'] || $ret['contactType']) {
                // 开启非员工注册验证时
                if (get_addon_config('thirdwork')['registerverify'] === '1') {
                    return ['errmsg' => '你不是该企业的成员'];
                } else {
                    $userinfo = [];
                }
            } else {
                // 用userid查用户详情
                $queryarr = [
                    'access_token'  => $this->getAccessToken(),
                    'userid'        => $ret['userid']
                ];
                $ret = Http::get(self::GET_USER_URL, $queryarr);
                $ret = (array) json_decode($ret, true);
                if (!$ret || $ret['errcode']) {
                    return ['errmsg' => '获取成员详情失败'];
                }
                $userinfo = $ret ? $ret : [];
                $userinfo['nickname'] = isset($userinfo['name']) ? $userinfo['name'] : $nick;
            }
            $data = [
                'access_token'  => '',
                'refresh_token' => '',
                'expires_in'    => 0,
                'openid'        => $openid,
                'userinfo'      => $userinfo
            ];
            return $data;
        }
        return ['errmsg' => '第三方平台授权失败'];
    }

    /**
     * 获取access_token
     * @return array
     */
    public function getAccessToken()
    {
        $cache = Cache::get('dingtalk_access_token');
        if ($cache) {
            if (isset($cache['access_token']) && time() < $cache['expire_time']) {
                return $cache['access_token'];
            }
        }

        $queryarr = array(
            'appkey'    => $this->config['appkey'],
            'appsecret' => $this->config['appsecret'],
        );
        $response = Http::get(self::GET_ACCESS_TOKEN_URL, $queryarr);
        $response = (array) json_decode($response, true);
        if (!$response['errcode']) {
            Cache::tag('thirdwork')->set('dingtalk_access_token', [
                'access_token'  => $response['access_token'],
                'expire_time'   => time() + 7200
            ]);
            return $response['access_token'];
        }
        return $response;
    }
    /**
     * 获取部门列表
     * @return array
     */
    public function getDepartmentList()
    {
        $queryarr = array(
            'access_token'  => $this->getAccessToken()
        );
        $response = Http::get(self::GET_DEPARTMENT_LIST_URL, $queryarr);
        $response = (array) json_decode($response, true);
        if (isset($response['department'])) {
            $data = [];
            foreach ($response['department'] as $v) {
                // 过滤家校通讯录
                if ($v['id'] < 0) {
                    continue;
                }
                $opened = isset($v['parentid']) ? false : true;
                $selected = isset($v['parentid']) ? false : true;
                $data[] = array('id' => $v['id'], 'parent' => isset($v['parentid']) ? $v['parentid'] : '#', 'text' => $v['name'], 'icon' => 'fa fa-folder-o', 'state' => ['opened' => $opened, 'selected' => $selected]);
            }
            return ['code' => 1, 'data' => $data];
        }
        return ['code' => 0, 'msg' => $response['errmsg'], 'data' => $response];
    }

    /**
     * 获取部门成员详情
     * @return array
     */
    public function getDepartmentUserList()
    {
        $params = request()->get();
        $queryarr = array(
            'access_token'  => $this->getAccessToken(),
            'department_id' => $params['department_id'],
            'offset'        => isset($params['offset']) ? $params['offset'] : 0,
            'size'          => isset($params['limit']) ? $params['limit'] : 10
        );
        $response = Http::get(self::GET_DEPARTMENT_USER_LIST_URL, $queryarr);
        $response = (array) json_decode($response, true);
        if (isset($response['userlist'])) {
            $data = [];
            foreach ($response['userlist'] as $v) {
                $data[] = array(
                    'userid'    => $v['userid'],
                    'avatar'    => isset($v['avatar']) ? $v['avatar'] : '',
                    'name'      => $v['name'],
                    'position'  => isset($v['position']) ? $v['position'] : '',
                    'mobile'    => isset($v['mobile']) ? $v['mobile'] : '',
                    'email'     => isset($v['email']) ? $v['email'] : '',
                    'active'    => $v['active']
                );
            }
            return ['code' => 1, 'data' => $data];
        }
        return ['code' => 0, 'msg' => $response['errmsg'], 'data' => $response];
    }

    /**
     * 获取部门成员人数
     * @return int
     */
    public function getDepartmentUserCount()
    {
        $params = request()->get();
        $queryarr = array(
            'access_token'  => $this->getAccessToken(),
            'deptId'        => $params['department_id'],
        );
        $response = Http::get(self::GET_DEPARTMENT_MEMBER_URL, $queryarr);
        $response = (array) json_decode($response, true);
        if (!$response['errcode'] && isset($response['userIds'])) {
            return ['code' => 1, 'data' => count($response['userIds'])];
        }
        return ['code' => 0, 'msg' => $response['errmsg'], 'data' => $response];
    }

    /**
     * 获取部门成员userid列表
     * @return array 成员userid数组
     */
    public function getDepartmentUserIds()
    {
        $params = request()->get();
        $queryarr = array(
            'access_token'  => $this->getAccessToken(),
            'deptId'        => $params['department_id'],
        );
        $response = Http::get(self::GET_DEPARTMENT_MEMBER_URL, $queryarr);
        $response = (array) json_decode($response, true);
        if (!$response['errcode'] && isset($response['userIds'])) {
            return ['code' => 1, 'data' => $response['userIds']];
        }
        return ['code' => 0, 'msg' => $response['errmsg'], 'data' => $response];
    }

    /**
     * 根据timestamp, appSecret计算签名值
     * @param timestamp $timestamp 时间戳
     * @return string
     */
    // 
    private function getSignature($timestamp)
    {
        $s = hash_hmac('sha256', $timestamp, $this->config['appsecret_qr'], true);
        $signature = base64_encode($s);
        return urlencode($signature);
    }
}
